///
/// 利用fork()及消息通信系统调用实现父子进程间的通信 (linux运行)
///
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

typedef struct
{
	long mtype;
	char mtext[256];
} message;

int main()
{
	pid_t pid;
	key_t key;
	int msgid;
	message msg;

	// 创建消息队列
	key = ftok("msgq.txt", 'A');		   // 使用ftok函数生成唯一的key
	msgid = msgget(key, IPC_CREAT | 0666); // 创建消息队列
	if (msgid < 0)
	{
		perror("msgget failed");
		exit(EXIT_FAILURE);
	}

	// 创建子进程
	pid = fork();
	if (pid < 0)
	{
		perror("fork failed");
		exit(EXIT_FAILURE);
	}

	if (pid == 0)
	{ // 子进程
		printf("Child process is running.\n");

		// 从消息队列中读取消息
		msgrcv(msgid, &msg, sizeof(message), 1, 0); // 阻塞等待类型为1的消息
		printf("Received message from parent: %s\n", msg.mtext);

		// 发送消息到消息队列
		sprintf(msg.mtext, "Hello parent, this is child.");
		msg.mtype = 2; // 消息类型为2
		msgsnd(msgid, &msg, sizeof(message), 0);

		exit(EXIT_SUCCESS);
	}
	else
	{ // 父进程
		printf("Parent process is running.\n");

		// 发送消息到消息队列
		sprintf(msg.mtext, "Hello child, this is parent.");
		msg.mtype = 1; // 消息类型为1
		msgsnd(msgid, &msg, sizeof(message), 0);

		// 等待子进程发送回复消息
		msgrcv(msgid, &msg, sizeof(message), 2, 0); // 阻塞等待类型为2的消息
		printf("Received message from child: %s\n", msg.mtext);
	}

	// 删除消息队列
	msgctl(msgid, IPC_RMID, NULL);

	return 0;
}
